package fr.neticar.webremoteclient.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ScrollPanel;

public class WRC implements EntryPoint {

	private WRCClientGatewayAsync remoteService;

	private boolean isReceivingImages = false;

	private TitlePanel titlePanel;

	private DockPanel mainPanel;

	private ScrollPanel remotePanel;

	private ImagePanel imagePanel;

	private LoginPanel loginPanel;

	public void onModuleLoad() {
		RootPanel rootPanel = RootPanel.get();
		rootPanel.add(getMainPanel());
	}

	private DockPanel getMainPanel() {
		if (this.mainPanel == null) {
			this.mainPanel = new DockPanel();
			this.mainPanel.add(this.getTitlePanel(), DockPanel.NORTH);
			this.mainPanel.setCellHeight(this.getTitlePanel(), "60");
			this.mainPanel.setCellWidth(this.getTitlePanel(), "100%");
			this.mainPanel.add(this.getLoginPanel(), DockPanel.WEST);
			this.mainPanel.add(this.getRemotePanel(), DockPanel.CENTER);
			this.mainPanel.setCellHeight(this.getRemotePanel(), "100%");
			this.mainPanel.setCellWidth(this.getRemotePanel(), "100%");
			this.mainPanel.setWidth("99%");
			this.mainPanel.setHeight("99%");
			this.mainPanel.setStyleName("mainpanel");
		}
		return this.mainPanel;
	}

	private LoginPanel getLoginPanel() {
		if (this.loginPanel == null) {
			this.loginPanel = new LoginPanel(this);
		}
		return this.loginPanel;
	}

	private TitlePanel getTitlePanel() {
		if (this.titlePanel == null) {
			this.titlePanel = new TitlePanel();
		}
		return this.titlePanel;
	}

	private Panel getRemotePanel() {
		if (this.remotePanel == null) {
			this.remotePanel = new ScrollPanel();
			this.remotePanel.setAlwaysShowScrollBars(false);
			this.remotePanel.add(this.getImagePanel());
			this.remotePanel.setWidth("100%");
			this.remotePanel.setHeight("100%");
			this.remotePanel.setStyleName("remotepanel");
		}
		return this.remotePanel;
	}

	private ImagePanel getImagePanel() {
		if (this.imagePanel == null) {
			this.imagePanel = new ImagePanel();
			this.imagePanel.addImagePanelListener(new ImagePanelListener() {

				public void onKeyboardEvent(KeyboardEventBean event) {
					getRemoteService().sendEvent(event, new AsyncCallback() {
						public void onFailure(Throwable caught) {
							throw new JavaScriptException("Error while sending keyboard event", caught.getMessage());
						}

						public void onSuccess(Object result) {
						}
					});
				}

				public void onMouseEvent(MouseEventBean event) {
					getRemoteService().sendEvent(event, new AsyncCallback() {
						public void onFailure(Throwable caught) {
							throw new JavaScriptException("Error while sending mouse event", caught.getMessage());
						}

						public void onSuccess(Object result) {
						}
					});
				}
			});
		}
		return this.imagePanel;
	}

	private WRCClientGatewayAsync getRemoteService() {
		if (this.remoteService == null) {
			this.remoteService = (WRCClientGatewayAsync) GWT.create(WRCClientGateway.class);
			ServiceDefTarget target = (ServiceDefTarget) this.remoteService;
			String baseURL = String.valueOf(GWT.getModuleBaseURL());
			// TODO : use this url with Jetty : baseURL = "/WebVNC/";
			target.setServiceEntryPoint((new StringBuffer(baseURL)).append("WRCClientGateway").toString());
		}
		return this.remoteService;
	}

	public void startVncViewer(String host, String port, String password) {
		final WRCClientGatewayAsync service = getRemoteService();
		AsyncCallback startViewerResponse = new AsyncCallback() {
			public void onFailure(Throwable caught) {
				
				getLoginPanel().setErrorMessage(caught.getMessage());
				getLoginPanel().switchToDisconnectedState();
				caught.printStackTrace();
			}

			public void onSuccess(Object result) {
				getLoginPanel().switchToConnectedState();
				updateImagePanelSize();
				startReceivingImages();
			}
		};
		service.startVNCClient(host, port, password, startViewerResponse);
	}

	public void stopVncViewer() {
		final WRCClientGatewayAsync service = getRemoteService();
		AsyncCallback stopViewerResponse = new AsyncCallback() {
			public void onFailure(Throwable caught) {
				getLoginPanel().switchToDisconnectedState();
				stopReceivingImages();
				getImagePanel().clear();
				getImagePanel().setSize("0", "0");
			}

			public void onSuccess(Object result) {
				getLoginPanel().switchToDisconnectedState();
				stopReceivingImages();
				getImagePanel().clear();
				getImagePanel().setSize("0", "0");
			}
		};
		service.stopVNCClient(stopViewerResponse);
	}
	
	
	private void updateImagePanelSize() {
		final WRCClientGatewayAsync service = getRemoteService();
		AsyncCallback getScreenHeightResponse = new AsyncCallback() {
			public void onFailure(Throwable caught) {

			}

			public void onSuccess(Object result) {
				final String string = "" + result;
				getImagePanel().setHeight(string);
			}
		};
		service.getScreenHeight(getScreenHeightResponse);
		
		AsyncCallback getScreenWidthResponse = new AsyncCallback() {
			public void onFailure(Throwable caught) {

			}

			public void onSuccess(Object result) {
				final String string = "" + result;
				getImagePanel().setWidth(string);
			}
		};
		service.getScreenWidth(getScreenWidthResponse);
		
	}

	private void startReceivingImages() {
		this.isReceivingImages = true;
		final WRCClientGatewayAsync service = getRemoteService();
		AsyncCallback pushSimulator = new AsyncCallback() {
			public void onFailure(Throwable caught) {
				Window.alert(caught.getMessage());
				isReceivingImages = false;
				GWT.log("Error", caught);
				if (isReceivingImages)
					service.getNextImage(this);
			}

			public void onSuccess(Object result) {
				ImagePropertyBean imagePropertyBean = (ImagePropertyBean) result;
				fireNextImage(imagePropertyBean);
				if (isReceivingImages)
					service.getNextImage(this);
			}
		};
		service.getNextImage(pushSimulator);
	}

	private void stopReceivingImages() {
		this.isReceivingImages = false;
	}

	public void fireNextImage(ImagePropertyBean imagePropertyBean) {
		int x = imagePropertyBean.getX();
		int y = imagePropertyBean.getY();
		int w = imagePropertyBean.getW();
		int h = imagePropertyBean.getH();
		String id = imagePropertyBean.getId();
		String baseURL = String.valueOf(GWT.getModuleBaseURL());
		// baseURL = "/WebRemoteClient/";
		String url = (new StringBuffer(baseURL)).append("imageProvider?id=").append(id).toString();
		Image image = new Image(url);
		image.setHeight("" + h);
		image.setWidth("" + w);
		this.getImagePanel().addImage(image, x, y);
	}

}
